﻿using System;
using System.Collections.ObjectModel;
using System.Diagnostics.CodeAnalysis;
using System.IO;
using System.Xml.Serialization;
using Sasa.QualityTools.CodeAnalysis.Common;

namespace Sasa.QualityTools.CodeAnalysis.FxCopIntegrator.Models
{
    [XmlRoot("Dictionary")]
    [SuppressMessage("Microsoft.Naming", "CA1711")]
    public class FxCopDictionary
    {
        private string path;


        public Words Words { get; set; }

        public Acronyms Acronyms { get; set; }


        private FxCopDictionary()
        {
            Words = new Words();
            Acronyms = new Acronyms();
        }


        public static FxCopDictionary Load(string path)
        {
            Logger.Info("Loading FxCop dictionary from '{0}'.", path);

            FxCopDictionary result = null;

            if (!File.Exists(path))
            {
                result = new FxCopDictionary();
            }
            else
            {
                using (var stream = File.Open(path, FileMode.Open, FileAccess.Read, FileShare.Read))
                {
                    var serializer = new XmlSerializer(typeof(FxCopDictionary));
                    result = (FxCopDictionary)serializer.Deserialize(stream);
                }
            }
            result.path = path;

            return result;
        }

        public void Save()
        {
            Logger.Info("Saving FxCop dictionary to '{0}'.", path);

            Directory.CreateDirectory(Path.GetDirectoryName(path));

            using (var stream = File.Open(path, FileMode.Create, FileAccess.Write, FileShare.Write))
            {
                var serializer = new XmlSerializer(typeof(FxCopDictionary));
                var namespaces = new XmlSerializerNamespaces();
                namespaces.Add("", "");
                serializer.Serialize(stream, this, namespaces);
            }
        }
    }


    public class Words
    {
        private Collection<string> recognized;

        private Collection<string> unrecognized;

        private Collection<DeprecatedTerm> deprecated;

        private Collection<CompoundTerm> compound;

        private Collection<string> discreteExceptions;


        [XmlArray]
        [XmlArrayItem("Word")]
        public Collection<string> Recognized { get { return recognized; } }

        [XmlArray]
        [XmlArrayItem("Word")]
        public Collection<string> Unrecognized { get { return unrecognized; } }

        [XmlArray]
        [XmlArrayItem("Term")]
        public Collection<DeprecatedTerm> Deprecated { get { return deprecated; } }

        [XmlArray]
        [XmlArrayItem("Term")]
        public Collection<CompoundTerm> Compound { get { return compound; } }

        [XmlArray]
        [XmlArrayItem("Term")]
        public Collection<string> DiscreteExceptions { get { return discreteExceptions; } }


        public Words()
        {
            recognized = new Collection<string>();
            unrecognized = new Collection<string>();
            deprecated = new Collection<DeprecatedTerm>();
            compound = new Collection<CompoundTerm>();
            discreteExceptions = new Collection<string>();
        }
    }


    public class Acronyms
    {
        private Collection<string> casingExceptions;


        [XmlArray]
        [XmlArrayItem("Acronym")]
        public Collection<string> CasingExceptions { get { return casingExceptions; } }


        public Acronyms()
        {
            casingExceptions = new Collection<string>();
        }
    }


    public class DeprecatedTerm
    {
        [XmlText]
        public string Value { get; set; }

        [XmlAttribute("PreferredAlternate")]
        public string Alternate { get; set; }
    }


    public class CompoundTerm
    {
        [XmlText]
        public string Value { get; set; }

        [XmlAttribute("CompoundAlternate")]
        public string Alternate { get; set; }
    }
}
